#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <Type.h>
#include <GlobalVar.h>
#include <Dict.h>
#include "Str.h"
#include "Function.h"

Type StringType = {
        .type=&TypeType,
        .dict=0,
        .name="Type String",
        .print=printString,
        .add=addString,
        .hash=hashString,
        .equal=equalString,
        .neq=neqString,
        .greater = greaterString,
        .less = lessString,
        .ge = geString,
        .le = leString,
        .allocate_instance=str_allocate_instance
};

void string_init(String* self, const char* chs, int length) {  //python字符串非c语言风格
    self->dict = dict_allocate_const();
    self->type = &StringType;
    self->length = length;
    memcpy(self->str,chs,length);
}

String* string_allocate(const char* chs){
    return string_allocate_const(chs,strlen(chs));
}

String* string_allocate_const(const char* chs, int length){
    String* temp = (String*)malloc(sizeof(String));
    memset(temp,0,sizeof(String));
    temp->str=(char*)malloc(sizeof(char)*length);
    string_init(temp,chs,length);
    return temp;
}

void string_destroy(String* self){
    free(self->str);
    free(self);
}

Object* str_allocate_instance(Object* type){
    return string_allocate("1");
}


/****************************虚函数的实现**********************/

Object* addString(Object* self, Object* other){
    String* s1 = (String*)self;
    String* s2 = (String*)other;
    char* chs = (char*)malloc(sizeof(char)*(s1->length+s2->length));
    for(int i = 0; i < s1->length; ++i){
        chs[i] = s1->str[i];
    }
    for(int i = 0; i < s2->length; ++i){
        chs[i+s1->length] = s2->str[i];
    }
    String* result = (String*)malloc(sizeof(String));
    string_init(result, chs, s1->length + s2->length);
    return (Object*)result;
}


void printString(Object* self){
    String* temp = (String*)self;
    for(int i = 0; i < temp->length; ++i)
        printf("%c", temp->str[i]);
}

int hashString(Object* self) {
    int result = 0;
    String* _self = (String*)self;
    for (int i = 0; i < _self->length; i++)
        result = 31 * result + _self->str[i];
    return result;
}


Object* greaterString(Object* self, Object* other){
    String* s1 = (String*)self;
    String* s2 = (String*)other;
    int len = s1->length > s2->length ? s2->length : s1->length;
    for(int i = 0; i < len; ++i){
        if(s1->str[i] > s2->str[i])
            return &True;
        if(s1->str[i] < s2->str[i])
            return &False;
    }
    if(s1->length > s2->length)
        return &True;
    return &False;
}



Object* equalString(Object* self, Object* other){
    if (self == other)
        return &True;
    if (hashString(self) == hashString(other))
        return &True;
    return &False;
}

Object* neqString(Object* self, Object* other){
    if(equalString(self, other) == &True)
        return &False;
    else return &True;
}

Object* geString(Object* self, Object* other){
    if((equalString(self, other) == &True) || (greaterString(self, other) == &True))
        return &True;
    else return &False;
}

Object* lessString(Object* self, Object* other){
    if(geString(self, other) == &True)
        return &False;
    else return &True;
}

Object* leString(Object* self, Object* other){
    if((equalString(self, other) == &True) || (lessString(self, other) == &True))
        return &True;
    else return &False;
}


Object* pvm_str_init(List* args){
    String* self= list_get(args,0);
    String* temp  = list_get(args,1);
    free(self->str);
    self->str = (char*)malloc(sizeof(char)*temp->length);
    memcpy(self->str,temp->str,temp->length);
    self->length=temp->length;
    return &None;
}

void pvm_init_str(){
    StringType.dict=dict_allocate_const();
    StringType.mro=list_allocate_const();
    function_insert_native("__init__",pvm_str_init,&StringType,2,NULL);
}